from django.shortcuts import render
# Create your views here.
from django.shortcuts import render
from django.http import JsonResponse
from button_app.core import DataOwnershipSystem
from types import SimpleNamespace
from datetime import datetime
import unittest
from core import DataOwnershipSystem
from cryptography.hazmat.primitives import serialization
from datetime import datetime
import json
import hashlib
import unittest
from core import DataOwnershipSystem
from cryptography.hazmat.primitives import serialization
from datetime import datetime, timedelta  # 添加timedelta导入
import json
import hashlib
from psycopg2.extras import Json  # 添加Json导入



def home(request):
    return render(request, 'home.html')

class TestDataOwnershipSystem(unittest.TestCase):
    @classmethod
    def setUpClass(cls):
        # 测试数据库配置
        cls.db_params = {
            'dbname': 'db427',
            'user': 'postgres',
            'password': '12345678',
            'host': 'localhost',
            'port': '5432'
        }

        # 创建测试数据库连接
        cls.system = DataOwnershipSystem(cls.db_params)

    @classmethod
    def tearDownClass(cls):
        # 清理测试数据库
        cls.system.close()

    def setUp(self):
        # 生成密钥对
        self.seller_private_key, self.seller_public_key = self.system.generate_key_pair()
        self.buyer_private_key, self.buyer_public_key = self.system.generate_key_pair()
        self.new_buyer_private_key, self.new_buyer_public_key = self.system.generate_key_pair()
        self.another_buyer_private_key, self.another_buyer_public_key = self.system.generate_key_pair()

        # 测试数据
        self.data = "This is some sensitive data to be sold"

        # 清空测试数据
        self._clean_test_data()

    def _clean_test_data(self):
        """清理测试数据"""
        with self.system.conn.cursor() as cur:
            cur.execute("TRUNCATE TABLE data_ownership CASCADE")
            cur.execute("TRUNCATE TABLE usage_tokens CASCADE")
            cur.execute("TRUNCATE TABLE transactions CASCADE")
            self.system.conn.commit()

    def _get_token_record(self, token_id):
        """从数据库获取令牌记录"""
        with self.system.conn.cursor() as cur:
            cur.execute("""
                SELECT encrypted_token, metadata, valid_until, generated_at, parent_token
                FROM usage_tokens 
                WHERE token_id = %s
            """, (token_id,))
            result = cur.fetchone()
            if not result:
                return None
            return {
                'encrypted_token': result[0],
                'metadata': result[1],
                'valid_until': result[2],
                'generation_time': result[3].isoformat(),
                'parent_token': result[4]
            }


    def test_ownership_registration_and_verification(self):
        # 注册所有权
        ownership_record = self.system.register_ownership(
            self.data, self.seller_private_key)

        # 从数据库获取签名
        data_hash = hashlib.sha256(self.data.encode()).hexdigest()
        with self.system.conn.cursor() as cur:
            cur.execute(
                "SELECT signature, public_key FROM data_ownership WHERE data_hash = %s",
                (data_hash,)
            )
            signature, public_key_pem = cur.fetchone()

        # 加载公钥
        public_key = serialization.load_pem_public_key(
            public_key_pem.encode()
        )

        # 验证所有权
        is_valid = self.system.verify_ownership(
            self.data,
            signature,
            public_key)
        self.assertTrue(is_valid)

        # 测试伪造签名
        fake_private_key, fake_public_key = self.system.generate_key_pair()
        is_valid = self.system.verify_ownership(
            self.data,
            signature,
            fake_public_key)
        self.assertFalse(is_valid)

    def test_token_generation_and_resale(self):
        # 1. 注册所有权
        ownership_record = self.system.register_ownership(
            self.data, self.seller_private_key)

        # 2. 生成初始使用权令牌
        token_id = self.system.generate_usage_token(
            self.data,
            self.seller_private_key,
            self.buyer_public_key,
            validity_period=365)

        # 验证初始令牌
        token_record = self._get_token_record(token_id)
        self.assertIsNotNone(token_record)

        decrypted_metadata = self.system._decrypt_with_paillier(token_record['encrypted_token'])

        # 标准化比较：转换为排序后的JSON字符串
        expected_metadata = {
            'data_hash': hashlib.sha256(self.data.encode()).hexdigest(),
            'seller_public_key': self.seller_public_key.public_bytes(
                encoding=serialization.Encoding.PEM,
                format=serialization.PublicFormat.SubjectPublicKeyInfo
            ).decode(),
            'buyer_public_key': self.buyer_public_key.public_bytes(
                encoding=serialization.Encoding.PEM,
                format=serialization.PublicFormat.SubjectPublicKeyInfo
            ).decode(),
            'valid_until': token_record['metadata']['valid_until'],
            'generation_time': token_record['generation_time'],
            'parent_token': None
        }

        self.assertEqual(
            json.dumps(decrypted_metadata, sort_keys=True),
            json.dumps(expected_metadata, sort_keys=True)
        )

        # 3. 第一级转售
        resale_token_id = self.system.resell_data(
            token_id,
            self.buyer_private_key,
            self.new_buyer_public_key,
            validity_period=180)

        # 验证第一级转售令牌
        resale_token_record = self._get_token_record(resale_token_id)
        self.assertIsNotNone(resale_token_record)

        decrypted_resale_metadata = self.system._decrypt_with_paillier(resale_token_record['encrypted_token'])

        expected_resale_metadata = {
            'data_hash': hashlib.sha256(self.data.encode()).hexdigest(),
            'seller_public_key': self.buyer_public_key.public_bytes(
                encoding=serialization.Encoding.PEM,
                format=serialization.PublicFormat.SubjectPublicKeyInfo
            ).decode(),
            'buyer_public_key': self.new_buyer_public_key.public_bytes(
                encoding=serialization.Encoding.PEM,
                format=serialization.PublicFormat.SubjectPublicKeyInfo
            ).decode(),
            'valid_until': resale_token_record['metadata']['valid_until'],
            'generation_time': resale_token_record['generation_time'],
            'parent_token': token_id
        }

        self.assertEqual(
            json.dumps(decrypted_resale_metadata, sort_keys=True),
            json.dumps(expected_resale_metadata, sort_keys=True)
        )

        # 4. 第二级转售
        second_resale_token_id = self.system.resell_data(
            resale_token_id,
            self.new_buyer_private_key,
            self.another_buyer_public_key,
            validity_period=90)

        # 验证第二级转售令牌
        second_resale_token_record = self._get_token_record(second_resale_token_id)
        self.assertIsNotNone(second_resale_token_record)
        '''
        self._get_token_record(second_resale_token_id) 通过唯一标识符查询令牌记录，
        属于密码学中的唯一性标识验证。我这么做可以确保令牌在系统中已注册且未被篡改，有点像数字证书的序列号验证
        '''
        decrypted_second_resale_metadata = self.system._decrypt_with_paillier(
            second_resale_token_record['encrypted_token'])
        '''
        _decrypt_with_paillier() 使用Paillier算法的私钥解密令牌密文。
        上面使用了Paillier来同态加密令牌，满足隐私保护的链式交易需求
        '''
        '''
        通过SHA-256哈希比对 data_hash，属于密码学哈希函数验证。
        哈希的雪崩效应确保即使原始数据微小变化也会导致哈希值巨变，有效防止数据篡改。
        公钥序列化采用PEM格式的 SubjectPublicKeyInfo 结构，遵循X.509标准，
        确保密钥交换的兼容性和可验证性
        '''
        expected_second_resale_metadata = {
            'data_hash': hashlib.sha256(self.data.encode()).hexdigest(),
            'seller_public_key': self.new_buyer_public_key.public_bytes(
                encoding=serialization.Encoding.PEM,
                format=serialization.PublicFormat.SubjectPublicKeyInfo
            ).decode(),
            'buyer_public_key': self.another_buyer_public_key.public_bytes(
                encoding=serialization.Encoding.PEM,
                format=serialization.PublicFormat.SubjectPublicKeyInfo
            ).decode(),
            'valid_until': second_resale_token_record['metadata']['valid_until'],
            'generation_time': second_resale_token_record['generation_time'],
            'parent_token': resale_token_id
        }

        self.assertEqual(
            json.dumps(decrypted_second_resale_metadata, sort_keys=True),
            json.dumps(expected_second_resale_metadata, sort_keys=True)
        )

        # 5. 验证权限衰减
        '''
        通过逐级递减的 valid_until 时间戳实现时效性控制，属于密码学中的时间绑定策略。
        采用ISO 8601时间格式和数字签名的时间戳（类似JWT的exp声明），确保令牌生命周期可验证且不可逆。
        assertLess 验证每一级令牌的有效期严格短于父级，形成 token_validity > resale_validity > second_resale_validity 的衰减链，防止无限转售。
        '''
        token_validity = datetime.fromisoformat(token_record['metadata']['valid_until'])
        resale_validity = datetime.fromisoformat(resale_token_record['metadata']['valid_until'])
        second_resale_validity = datetime.fromisoformat(second_resale_token_record['metadata']['valid_until'])

        self.assertLess(second_resale_validity, resale_validity)
        self.assertLess(resale_validity, token_validity)

        # 6. 验证令牌链
        self.assertEqual(second_resale_token_record['parent_token'], resale_token_id)
        self.assertEqual(resale_token_record['parent_token'], token_id)
        self.assertIsNone(token_record['parent_token'])





def setUp(obj):
    # 随机生成密钥对
    obj.seller_private_key, obj.seller_public_key = obj.system.generate_key_pair()
    obj.buyer_private_key, obj.buyer_public_key = obj.system.generate_key_pair()
    obj.new_buyer_private_key, obj.new_buyer_public_key = obj.system.generate_key_pair()
    obj.another_buyer_private_key, obj.another_buyer_public_key = obj.system.generate_key_pair()

    # 测试数据
    obj.data = "This is some sensitive data to be sold"

    # 清空测试数据
    _clean_test_data(obj)

def _clean_test_data(obj):
    """清理测试数据"""
    with obj.system.conn.cursor() as cur:
        cur.execute("TRUNCATE TABLE data_ownership CASCADE")
        cur.execute("TRUNCATE TABLE usage_tokens CASCADE")
        cur.execute("TRUNCATE TABLE transactions CASCADE")
        obj.system.conn.commit()

def ttest_transaction_chain_integrity(obj):
    # 交易链完整性测试

    obj.system.output_to_lst("\n    开始交易链完整性测试    ")
    # 1. （自动）注册所有权
    obj.system.output_to_lst("\n1. 注册所有权...")
    reg_result = obj.system.register_ownership(obj.data, obj.seller_private_key)
    obj.system.output_to_lst(f"注册结果: {reg_result}")
    # 2. 生成使用权令牌
    obj.system.output_to_lst("\n2. 生成使用权令牌...")
    token_id = obj.system.generate_usage_token(
        obj.data,
        obj.seller_private_key,
        obj.buyer_public_key)
    obj.system.output_to_lst(f"原始令牌ID: {token_id}")

    # 3. 转售
    obj.system.output_to_lst("\n3. 转售令牌...")
    new_buyer_private_key, new_buyer_public_key = obj.system.generate_key_pair()
    resale_token_id = obj.system.resell_data(
        token_id,
        obj.buyer_private_key,
        new_buyer_public_key)
    obj.system.output_to_lst(f"新令牌ID: {resale_token_id}")

    # 4. 验证交易链
    obj.system.output_to_lst("\n4. 验证交易链...")
    is_valid = obj.system.verify_transaction_chain()
    obj.system.output_to_lst(f"交易链验证结果: {is_valid}")

    # 5. 打印所有交易记录
    obj.system.output_to_lst("\n5. 交易记录详情:")
    with obj.system.conn.cursor() as cur:
        cur.execute("""
            SELECT transaction_id, transaction_type, transaction_hash, 
                   previous_hash, timestamp 
            FROM transactions 
            ORDER BY transaction_id
        """)
        for row in cur.fetchall():
            obj.system.output_to_lst(
                f"ID:{row[0]} Type:{row[1]} Hash:{row[2][:16]}... Prev:{row[3][:16] if row[3] else 'None'} Time:{row[4]}")




def get_data(request):
    obj = SimpleNamespace()
    obj.system = {}
    db_params = {
        'dbname': 'db427',
        'user': 'postgres',
        'password': '12345678',
        'host': 'localhost',
        'port': '5432'
    }
    data = []
    # 创建测试数据库连接
    obj.system = DataOwnershipSystem(db_params)
    setUp(obj)
    ttest_transaction_chain_integrity(obj)
    data = obj.system.get_web_data();


    return JsonResponse({'lines': data})

def ttest_tamper_detection(obj):
    """测试篡改交易时间戳后的检测能力"""
    obj.system.output_to_lst("\n    开始篡改检测测试    ")


    # 1. 生成基础交易链
    obj.system.output_to_lst("\n1. 生成基础交易链...")
    obj.system.register_ownership(obj.data, obj.seller_private_key)
    token_id = obj.system.generate_usage_token(
        obj.data,
        obj.seller_private_key,
        obj.buyer_public_key)
    obj.system.resell_data(
        token_id,
        obj.buyer_private_key,
        obj.new_buyer_public_key)

    # 2. 获取最近一笔交易记录
    obj.system.output_to_lst("\n2. 获取最近交易记录...")
    with obj.system.conn.cursor() as cur:
        cur.execute("""
            SELECT transaction_id, timestamp 
            FROM transactions 
            ORDER BY transaction_id DESC 
            LIMIT 1
        """)
        original_trans = cur.fetchone()
        obj.system.output_to_lst(f"原始交易ID: {original_trans[0]}，时间: {original_trans[1]}")

    # 3. 篡改时间戳
    obj.system.output_to_lst("\n3. 篡改时间戳字段...")
    new_timestamp = datetime.now().isoformat()
    with obj.system.conn.cursor() as cur:
        cur.execute("""
            UPDATE transactions 
            SET timestamp = %s 
            WHERE transaction_id = %s
        """, (new_timestamp, original_trans[0]))
        obj.system.conn.commit()
    obj.system.output_to_lst(f"修改时间戳为: {new_timestamp}")

    # 4. 验证交易链完整性
    obj.system.output_to_lst("\n4. 验证篡改后的交易链...")
    is_valid = obj.system.verify_transaction_chain()
    obj.system.output_to_lst(f"验证结果: {is_valid}")

    # 5. 断言检测到篡改
    # obj.assertFalse(is_valid, "系统应检测到时间戳篡改")
    obj.system.output_to_lst(f"系统应检测到时间戳篡改: {is_valid}")

    # 6. 显示篡改后的交易记录（调试用）
    obj.system.output_to_lst("\n5. 篡改后的交易记录:")
    with obj.system.conn.cursor() as cur:
        cur.execute("""
            SELECT transaction_id, transaction_hash, 
                   previous_hash, timestamp 
            FROM transactions 
            ORDER BY transaction_id
        """)
        for row in cur.fetchall():
            status = "⚠️ 已篡改" if row[0] == original_trans[0] else "✅ 正常"
            obj.system.output_to_lst(
                f"{status} ID:{row[0]} Hash:{row[1][:16]}... Prev:{row[2][:16] if row[2] else 'None'} Time:{row[3]}")


def get_data2(request):
    obj = SimpleNamespace()
    obj.system = {}
    db_params = {
        'dbname': 'db427',
        'user': 'postgres',
        'password': '12345678',
        'host': 'localhost',
        'port': '5432'
    }
    data = []
    # 创建测试数据库连接
    obj.system = DataOwnershipSystem(db_params)
    setUp(obj)
    ttest_tamper_detection(obj)

    data = obj.system.get_web_data();
    return JsonResponse({'lines': data})
